package com.musicdaze.utils;

import java.io.File;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

/**
 * Used to load jars to class path. This loader must then be used to create instances
 * of those classes.
 * <br>
 * Static global loader is loaded on instantiation of virtual machine.
 * @author Mikey Fujihara
 */
public class JarLoader extends URLClassLoader{
  public static JarLoader loader;
  static{
    loader = new JarLoader(new URL[0], JarLoader.class.getClassLoader());
  }
  /**
   * Private constructor for constructing the JarLoader.
   * @param urls
   * @param parent
   */
  private JarLoader(URL[] urls, ClassLoader parent) {
    super(urls, parent);
  }
  /**
   * Loads the class first from the url loader, then
   * from the parents.
   * @return the class
   */
  @Override
  public Class<?> loadClass(String name) throws ClassNotFoundException{
    Class<?> c = findLoadedClass(name);
    if (c ==null){
      try {
        c = findClass(name);
        return c;
      }
      catch (ClassNotFoundException e) {
        return super.loadClass(name);
      }
    }
    else{
      return c;
    }
  }
  /**
   * Adds the specified path to the class loader.
   * @param path the path to add
   * @return true if the path was added; false otherwise
   */
  public boolean addDirectory(String path){
    File file = new File(path);
    if (!file.exists()){
      return false;
    }
    try {
      String s = path;
      Field field = ClassLoader.class.getDeclaredField("usr_paths");
      field.setAccessible(true);
      String[] paths = (String[])field.get(null);
      for (int i = 0; i < paths.length; i++) {
        if (s.equals(paths[i])) {
          return true;
        }
      }
      String[] tmp = new String[paths.length+1];
      System.arraycopy(paths,0,tmp,0,paths.length);
      tmp[paths.length] = s;
      field.set(null,tmp);
      URL direct = new URL("file://" + file.getAbsolutePath() + "/");
      addURL(direct);
    }
    catch (MalformedURLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      return false;
    }
    catch (SecurityException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    catch (NoSuchFieldException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    catch (IllegalArgumentException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    catch (IllegalAccessException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    return true;
  }
  /**
   * Adds the specified jar to the class loader, given its path.
   * @param path the path to the jar
   * @return whether the jar was successfully added or not; true if added, false otherwise
   */
  public boolean addJar(String path){
    File file = new File(path);
    if (!file.exists()){
      return false;
    }
    try {
      URL jar = new URL("jar:file:" + file.getAbsolutePath() + "!/");
      addURL(jar);
    }
    catch (MalformedURLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      return false;
    }
    return true;
  }
}
